home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Games / NetHack 3.1.3 / source / src / dothrow.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-01  |  21.9 KB  |  838 lines  |  [TEXT/R*ch]

  1. /*    SCCS Id: @(#)dothrow.c    3.1    93/06/15    */
  2. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
  3. /* NetHack may be freely redistributed.  See license for details. */
  4.  
  5. /* Contains code for 't' (throw) */
  6.  
  7. #include "hack.h"
  8.  
  9. static int FDECL(gem_accept, (struct monst *, struct obj *));
  10. static int FDECL(throw_gold, (struct obj *));
  11. static void FDECL(check_shop_obj, (struct obj *,XCHAR_P,XCHAR_P,BOOLEAN_P));
  12.  
  13. static NEARDATA const char toss_objs[] =
  14.     { ALLOW_COUNT, GOLD_CLASS, ALL_CLASSES, WEAPON_CLASS, 0 };
  15. extern boolean notonhead;    /* for long worms */
  16.  
  17. int
  18. dothrow()
  19. {
  20.     register struct obj *obj;
  21.  
  22.     if(check_capacity(NULL)) return(0);
  23.     obj = getobj(toss_objs, "throw");
  24.     /* it is also possible to throw food */
  25.     /* (or jewels, or iron balls... ) */
  26.  
  27.     if(!obj || !getdir(NULL)) {       /* ask "in what direction?" */
  28.         if (obj && obj->oclass == GOLD_CLASS) {
  29.             u.ugold += obj->quan;
  30.             flags.botl = 1;
  31.             dealloc_obj(obj);
  32.         }
  33.         return(0);
  34.     }
  35.  
  36.     if(obj->oclass == GOLD_CLASS) return(throw_gold(obj));
  37.  
  38.     if(!canletgo(obj,"throw"))
  39.         return(0);
  40.     if (obj->oartifact == ART_MJOLLNIR && obj != uwep) {
  41.         You("must be wielding %s in order to throw it.", xname(obj));
  42.         return(0);
  43.     }
  44.     if ((obj->oartifact == ART_MJOLLNIR && ACURR(A_STR) != 125)
  45.        || (obj->otyp == BOULDER
  46. #ifdef POLYSELF
  47.                     && !throws_rocks(uasmon)
  48. #endif
  49.                                 )) {
  50.         pline("It's too heavy.");
  51.         return(1);
  52.     }
  53.     if(!u.dx && !u.dy && !u.dz) {
  54.         You("cannot throw an object at yourself.");
  55.         return(0);
  56.     }
  57.     u_wipe_engr(2);
  58.  
  59.     if(obj == uwep) {
  60.         if(welded(obj)) {
  61.         weldmsg(obj, FALSE);
  62.         return(1);
  63.         }
  64.         if(obj->quan > 1L)
  65.         setuwep(splitobj(obj, 1L));
  66.         else {
  67.         setuwep((struct obj *)0);
  68.         if (uwep) return(1); /* unwielded, died, rewielded */
  69.         }
  70.     }
  71.     else if(obj->quan > 1L)
  72.         (void) splitobj(obj, 1L);
  73.     freeinv(obj);
  74.     return(throwit(obj));
  75. }
  76.  
  77. void
  78. hitfloor(obj)
  79. register struct obj *obj;
  80. {
  81.     if (IS_SOFT(levl[u.ux][u.uy].typ) || u.uinwater) {
  82.         dropy(obj);
  83.         return;
  84.     }
  85.     if (IS_ALTAR(levl[u.ux][u.uy].typ)) doaltarobj(obj);
  86.     else
  87.         pline("%s hit%s the %s.", Doname2(obj), 
  88.               (obj->quan == 1L) ? "s" : "", surface(u.ux,u.uy));
  89.     if (breaks(obj, TRUE)) return;
  90.     else if(obj->oclass == POTION_CLASS) {
  91.         pline("The flask%s break%s, and you smell a peculiar odor...",
  92.               plur(obj->quan), (obj->quan == 1L) ? "s" : "");
  93.         potionbreathe(obj);
  94.         if(*u.ushops)
  95.             check_shop_obj(obj, u.ux, u.uy, TRUE);
  96.         obfree(obj, (struct obj *)0);
  97.     } else {
  98.         if(ship_object(obj, u.ux, u.uy, FALSE)) 
  99.             return;
  100.         dropy(obj);
  101.     }
  102. }
  103.  
  104. /*
  105.  * The player moves through the air for a few squares as a result of
  106.  * throwing or kicking something.  To simplify matters, bumping into monsters
  107.  * won't cause damage but will wake them and make them angry.
  108.  * Auto-pickup isn't done, since you don't have control over your movements
  109.  * at the time.
  110.  * dx and dy should be the direction of the hurtle, not of the original
  111.  * kick or throw.
  112.  */
  113. void
  114. hurtle(dx, dy, range)
  115.     int dx, dy, range;
  116. {
  117.     register struct monst *mon;
  118.     struct obj *obj;
  119.     int nx, ny;
  120.  
  121.     if(!range || (!dx && !dy) || u.ustuck) return; /* paranoia */
  122.  
  123.     nomul(-range);
  124.     You("%s in the opposite direction.", range > 1 ? "hurtle" : "float");
  125.     while(range--) {
  126.     nx = u.ux + dx;
  127.     ny = u.uy + dy;
  128.  
  129.     if(!isok(nx,ny)) break;
  130.     if(IS_ROCK(levl[nx][ny].typ) || closed_door(nx,ny) ||
  131.        (IS_DOOR(levl[nx][ny].typ) && (levl[nx][ny].doormask & D_ISOPEN))) {
  132.         pline("Ouch!");
  133.         losehp(rnd(2+range), IS_ROCK(levl[nx][ny].typ) ?
  134.            "bumping into a wall" : "bumping into a door", KILLED_BY);
  135.         break;
  136.     }
  137.  
  138.     if ((obj = sobj_at(BOULDER,nx,ny)) != 0) {
  139.         You("bump into a %s.  Ouch!", xname(obj));
  140.         losehp(rnd(2+range), "bumping into a boulder", KILLED_BY);
  141.         break;
  142.     }
  143.  
  144.     u.ux = nx;
  145.     u.uy = ny;
  146.     newsym(u.ux - dx, u.uy - dy);
  147.     if ((mon = m_at(u.ux, u.uy)) != 0) {
  148.         You("bump into %s.", a_monnam(mon));
  149.         wakeup(mon);
  150.         if(Is_airlevel(&u.uz))
  151.         mnexto(mon);
  152.         else {
  153.         /* sorry, not ricochets */
  154.         u.ux -= dx;
  155.         u.uy -= dy;
  156.         }
  157.         range = 0;
  158.     }
  159.  
  160.     newsym(u.ux, u.uy);
  161.  
  162.     if(range) {
  163.         flush_screen(1);
  164.         delay_output();
  165.     }
  166.     }
  167. }
  168.  
  169. static void
  170. check_shop_obj(obj, x, y, broken)
  171. register struct obj *obj;
  172. register xchar x, y;
  173. register boolean broken;
  174. {
  175.     register struct monst *shkp = 
  176.             shop_keeper(*in_rooms(u.ux, u.uy, SHOPBASE));
  177.  
  178.     if(!shkp) return;
  179.     if(!inside_shop(u.ux, u.uy)) return;
  180.  
  181.     if(broken) {
  182.             if(obj->unpaid) {
  183.             (void)stolen_value(obj, u.ux, u.uy, 
  184.                  (shkp && shkp->mpeaceful), FALSE);
  185.             subfrombill(obj, shkp);
  186.         }
  187.         return;
  188.     }
  189.  
  190.         if(!costly_spot(x, y) ||
  191.                *in_rooms(u.ux, u.uy, 0) != *in_rooms(x, y, 0)) { 
  192.             if(!inside_shop(x, y) && obj->unpaid) {
  193.             (void)stolen_value(obj, u.ux, u.uy, 
  194.                  (shkp && shkp->mpeaceful), FALSE);
  195.             subfrombill(obj, shkp);
  196.         }
  197.     } else
  198.             if(costly_spot(u.ux, u.uy) && costly_spot(x, y)) {
  199.             if(obj->unpaid) subfrombill(obj, shkp);
  200.             else if(!(x == shkp->mx && y == shkp->my))
  201.                     sellobj(obj, x, y);
  202.         }
  203. }
  204.  
  205.  
  206. int
  207. throwit(obj)
  208. register struct obj *obj;
  209. {
  210.     register struct monst *mon;
  211.     register int range, urange;
  212.     boolean impaired = (Confusion || Stunned || Blind ||
  213.                Hallucination || Fumbling);
  214.     int do_death = 0;
  215.  
  216.     if ((obj->cursed || obj->greased) && (u.dx || u.dy) && !rn2(7)) {
  217.         boolean slipok = TRUE;
  218.         if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
  219.         && uwep && (objects[obj->otyp].w_propellor > 0) &&
  220.         (objects[obj->otyp].w_propellor ==
  221.                                              -objects[uwep->otyp].w_propellor))
  222.         pline("%s misfires!", The(xname(obj)));
  223.         else {
  224.         /* only slip if it's greased or meant to be thrown */
  225.         if(obj->greased ||
  226.            (obj->otyp >= DART && obj->otyp <= JAVELIN) ||
  227.            (obj->otyp >= DAGGER && obj->otyp <= CRYSKNIFE &&
  228.             obj->otyp != ATHAME) || obj->otyp == WAR_HAMMER)
  229.             pline("%s slips as you throw it!", The(xname(obj)));
  230.         else slipok = FALSE;
  231.         }
  232.         if (slipok) {
  233.         u.dx = rn2(3)-1;
  234.         u.dy = rn2(3)-1;
  235.         if (!u.dx && !u.dy) u.dz = 1;
  236.         impaired = TRUE;
  237.         }
  238.     }
  239.  
  240.     if(u.uswallow) {
  241.         mon = u.ustuck;
  242.         bhitpos.x = mon->mx;
  243.         bhitpos.y = mon->my;
  244.     } else if(u.dz) {
  245.       if (u.dz < 0 && pl_character[0] == 'V' &&
  246.           obj->oartifact == ART_MJOLLNIR && !impaired) {
  247.           pline("%s hits the ceiling and returns to your hand!",
  248.             The(xname(obj)));
  249.           obj = addinv(obj);
  250.           (void) encumber_msg();
  251.           setuwep(obj);
  252.           return(1);
  253.       }
  254.       if (u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) {
  255.         pline("%s hits the ceiling, then falls back on top of your %s.",
  256.         Doname2(obj),        /* note: obj->quan == 1 */
  257.         body_part(HEAD));
  258.         if(obj->oclass == POTION_CLASS)
  259.         potionhit(&youmonst, obj);
  260.         else {
  261.             int dmg = rnd((int)(obj->owt));
  262.           
  263.         if (uarmh) {
  264.             if(is_metallic(uarmh)) {
  265.                 pline("Fortunately, you are wearing a hard helmet.");
  266.             dmg = 1;
  267.             } else if (flags.verbose)
  268.                 Your("%s does not protect you.", xname(uarmh));
  269.         } else if (obj->otyp == CORPSE &&
  270.                 obj->corpsenm == PM_COCKATRICE) {
  271. #ifdef POLYSELF
  272.             if(!resists_ston(uasmon))
  273.             if(!(poly_when_stoned(uasmon) &&
  274.                     polymon(PM_STONE_GOLEM))) {
  275. #endif
  276.             killer = doname(obj);
  277.             You("turn to stone.");
  278.             do_death = STONING;
  279. #ifdef POLYSELF
  280.             }
  281. #endif
  282.         }
  283.  
  284.         if (!breaks(obj, TRUE)) {
  285.             if(!ship_object(obj, u.ux, u.uy, FALSE)) {
  286.             dropy(obj);
  287.             }
  288.         }
  289.         if (do_death == STONING)
  290.             done(STONING);
  291.         else
  292.             losehp(dmg, "falling object", KILLED_BY_AN);
  293.         }
  294.       } else hitfloor(obj);
  295.       return(1);
  296.  
  297.     } else if(obj->otyp == BOOMERANG && !Underwater) {
  298.         if(Is_airlevel(&u.uz) || Levitation) hurtle(-u.dx, -u.dy, 1);
  299.         mon = boomhit(u.dx, u.dy);
  300.         if(mon == &youmonst) {        /* the thing was caught */
  301.             exercise(A_DEX, TRUE);
  302.             (void) addinv(obj);
  303.             (void) encumber_msg();
  304.             return(1);
  305.         }
  306.     } else {
  307.         urange = (int)(ACURRSTR)/2;
  308.         range = urange - (int)(obj->owt/40);
  309.         if (obj == uball) {
  310.             if (u.ustuck) range = 1;
  311.             else if (range >= 5) range = 5;
  312.         }
  313.         if (range < 1) range = 1;
  314.  
  315.         if ((obj->oclass == WEAPON_CLASS || obj->oclass == GEM_CLASS)
  316.                     && uwep && objects[obj->otyp].w_propellor) {
  317.             if (objects[obj->otyp].w_propellor ==
  318.                                  -objects[uwep->otyp].w_propellor)
  319.             range++;
  320.             else
  321.             range /= 2;
  322.         }
  323.  
  324.         if (Is_airlevel(&u.uz) || Levitation) {
  325.             /* action, reaction... */
  326.             urange -= range;
  327.             if(urange < 1) urange = 1;
  328.             range -= urange;
  329.             if(range < 1) range = 1;
  330.         }
  331.  
  332. #ifdef POLYSELF
  333.         if (obj->otyp == BOULDER) range = 20;
  334. #endif
  335.         if (obj == uball && u.utrap && u.utraptype == TT_INFLOOR)
  336.             range = 1;
  337.  
  338.         if (Underwater) range = 1;
  339.  
  340.         mon = bhit(u.dx,u.dy,range,THROWN_WEAPON,
  341.                (int (*)()) 0,(int (*)()) 0,obj);
  342.  
  343.         /* have to do this after bhit() so u.ux & u.uy are correct */
  344.         if(Is_airlevel(&u.uz) || Levitation)
  345.             hurtle(-u.dx, -u.dy, urange);
  346.     }
  347.     if(mon) {
  348.         if(mon->isshk && (!inside_shop(u.ux, u.uy) ||
  349.            !index(in_rooms(mon->mx, mon->my, SHOPBASE), *u.ushops))) { 
  350.             if(obj->otyp == PICK_AXE) {
  351.                 register struct obj *otmp;
  352.  
  353.             /* check if the pick axe was caught through  */
  354.             /* a successful call to shkcatch() in bhit() */
  355.                     for (otmp = mon->minvent; otmp; otmp = otmp->nobj)
  356.                      if (otmp == obj) return(1);
  357.             }
  358.             wakeup(mon);
  359.             hot_pursuit(mon);
  360.         }
  361.         (void) snuff_candle(obj);
  362.         /* awake monster if sleeping */
  363.         wakeup(mon);
  364.         notonhead = (bhitpos.x != mon->mx || bhitpos.y != mon->my);
  365.         if(thitmonst(mon, obj)) return(1);
  366.     }
  367.     if(!u.uswallow) {
  368.         /* the code following might become part of dropy() */
  369.         int obj_glyph = obj_to_glyph(obj);
  370.         boolean gone = FALSE;
  371.  
  372.         if (obj->oartifact == ART_MJOLLNIR &&
  373.             pl_character[0] == 'V' && rn2(100)) {
  374.             /* we must be wearing Gauntlets of Power to get here */
  375.  
  376.             /* might already be our location (bounced off a wall) */
  377.             if (bhitpos.x != u.ux || bhitpos.y != u.uy) {
  378.             int x = bhitpos.x - u.dx, y = bhitpos.y - u.dy;
  379.  
  380.             tmp_at(DISP_FLASH, obj_glyph);
  381.             while(x != u.ux || y != u.uy) {
  382.                 tmp_at(x, y);
  383.                 delay_output();
  384.                 x -= u.dx; y -= u.dy;
  385.             }
  386.             tmp_at(DISP_END, 0);
  387.             }
  388.  
  389.             if (!impaired && rn2(100)) {
  390.             pline("%s returns to your hand!", The(xname(obj)));
  391.             obj = addinv(obj);
  392.             (void) encumber_msg();
  393.             setuwep(obj);
  394.             if(cansee(bhitpos.x, bhitpos.y))
  395.                 newsym(bhitpos.x,bhitpos.y);
  396.             } else {
  397.             int dmg = rnd(4);
  398.             if (Blind)
  399.                 pline("%s hits your %s!",
  400.                   The(xname(obj)), body_part(ARM));
  401.             else
  402.                 pline("%s flies back toward you, hitting your %s!",
  403.                   The(xname(obj)), body_part(ARM));
  404.             (void) artifact_hit((struct monst *) 0, &youmonst,
  405.                         obj, &dmg, 0);
  406.             losehp(dmg, xname(obj), KILLED_BY);
  407.             if(ship_object(obj, u.ux, u.uy, FALSE)) 
  408.                     return (1);
  409.             dropy(obj);
  410.             }
  411.             return (1);
  412.         }
  413.         if (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) && !u.uinwater &&
  414.             obj->oclass == POTION_CLASS && rn2(2)) {
  415.             if(distu(bhitpos.x, bhitpos.y) < 3 && rn2(5)) {
  416.             pline("The flask breaks, and you smell a peculiar odor...");
  417.             potionbreathe(obj);
  418.             } else if(!Blind)
  419.             pline("The flask breaks.");
  420.             else pline("Crash!");
  421.             if(*u.ushops)
  422.                 check_shop_obj(obj, bhitpos.x, bhitpos.y, TRUE);
  423.             obfree(obj, (struct obj *)0);
  424.             gone = TRUE;
  425.         }
  426.         if (gone || (!IS_SOFT(levl[bhitpos.x][bhitpos.y].typ) &&
  427.                  breaks(obj, TRUE))) {
  428.             tmp_at(DISP_FLASH, obj_glyph);
  429.             tmp_at(bhitpos.x, bhitpos.y);
  430.             delay_output();
  431.             tmp_at(DISP_END, 0);
  432.             return(1);
  433.         }
  434.         if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
  435.         if(obj->otyp == CRYSKNIFE)
  436.             obj->otyp = WORM_TOOTH;
  437.             if(mon && mon->isshk && obj->otyp == PICK_AXE) {
  438.                 mpickobj(mon, obj);
  439.             if(*u.ushops)
  440.                 check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
  441.             return(1);
  442.         }
  443.         (void) snuff_candle(obj);
  444.         if(!mon && obj != uball) {
  445.             if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE))
  446.                 return(1);
  447.         }
  448.         obj->nobj = fobj;
  449.         fobj = obj;
  450.         place_object(obj, bhitpos.x, bhitpos.y);
  451.         if(*u.ushops && obj != uball)
  452.             check_shop_obj(obj, bhitpos.x, bhitpos.y, FALSE);
  453.         stackobj(obj);
  454.         if (obj == uball) drop_ball(bhitpos.x, bhitpos.y);
  455.         if(cansee(bhitpos.x, bhitpos.y)) newsym(bhitpos.x,bhitpos.y);
  456.     } else {
  457.         /* ball is not picked up by monster */
  458.         if (obj != uball) mpickobj(u.ustuck,obj);
  459.     }
  460.     return(1);
  461. }
  462.  
  463. int
  464. thitmonst(mon, obj)
  465. register struct monst *mon;
  466. register struct obj   *obj;
  467. {
  468.     register int    tmp; /* Base chance to hit */
  469.     register int    disttmp; /* distance modifier */
  470.  
  471.     /* Differences from melee weapons:
  472.      *
  473.      * Dex still gives a bonus, but strength does not.
  474.      * Polymorphed players lacking attacks may still throw.
  475.      * There's a base -1 to hit.
  476.      * No bonuses for fleeing or stunned targets (they don't dodge
  477.      *    melee blows as readily, but dodging arrows is hard anyway).
  478.      * Not affected by traps, etc.
  479.      * Certain items which don't in themselves do damage ignore tmp.
  480.      * Distance and monster size affect chance to hit.
  481.      */
  482.     tmp = -1 + Luck + find_mac(mon);
  483. #ifdef POLYSELF
  484.     if (u.umonnum >= 0) tmp += uasmon->mlevel;
  485.     else
  486. #endif
  487.         tmp += u.ulevel;
  488.     if(ACURR(A_DEX) < 4) tmp -= 3;
  489.     else if(ACURR(A_DEX) < 6) tmp -= 2;
  490.     else if(ACURR(A_DEX) < 8) tmp -= 1;
  491.     else if(ACURR(A_DEX) >= 14) tmp += (ACURR(A_DEX) - 14);
  492.  
  493.     /* modify to-hit depending on distance; but keep it sane */
  494.     disttmp = 3 - distmin(u.ux, u.uy, mon->mx, mon->my);
  495.     if(disttmp < -4) disttmp = -4;
  496.     tmp += disttmp;
  497.  
  498.     /* it's easier to hit a larger target */
  499.     if(bigmonst(mon->data)) tmp++;
  500.  
  501.     /* gloves are a hinderance to proper use of bows */
  502.     if (uarmg && uwep && -objects[uwep->otyp].w_propellor == WP_BOW) {
  503.         switch(uarmg->otyp) {
  504.             case GAUNTLETS_OF_POWER:    /* metal */
  505.                 tmp -= 2;
  506.                 break;
  507.             case GAUNTLETS_OF_FUMBLING:
  508.                 tmp -= 3;
  509.                 break;
  510.             case LEATHER_GLOVES:
  511.             case GAUNTLETS_OF_DEXTERITY:
  512.                 break;
  513.             default: impossible("Unknown type of gloves (%d)",
  514.                 uarmg->otyp);
  515.         }
  516.     }
  517.  
  518.     if(mon->msleep) {
  519.         mon->msleep = 0;
  520.         tmp += 2;
  521.     }
  522.     if(!mon->mcanmove || !mon->data->mmove) {
  523.         tmp += 4;
  524.         if(!rn2(10)) {
  525.             mon->mcanmove = 1;
  526.             mon->mfrozen = 0;
  527.         }
  528.     }
  529.     if (is_orc(mon->data) && pl_character[0]=='E') tmp++;
  530.     if (u.uswallow && mon == u.ustuck) tmp += 1000; /* Guaranteed hit */
  531.  
  532.     if(obj->oclass == GEM_CLASS && mon->data->mlet == S_UNICORN) {
  533.         if (mon->mtame) {
  534.             pline("%s catches and drops %s.",
  535.                 Monnam(mon), the(xname(obj)));
  536.             return(0);
  537.         } else {
  538.             pline("%s catches %s.", Monnam(mon), the(xname(obj)));
  539.             return(gem_accept(mon, obj));
  540.         }
  541.     }
  542. #ifdef MULDGN
  543.     /* don't make game unwinnable if naive player throws artifact
  544.        at leader.... */
  545.     if (mon->data->msound == MS_LEADER && is_quest_artifact(obj)) {
  546.         if (mon->mcanmove)
  547.             pline("%s ignores %s.", Monnam(mon), the(xname(obj)));
  548.         return(0);
  549.     }
  550. #endif
  551.     if(obj->oclass == WEAPON_CLASS || obj->otyp == PICK_AXE ||
  552.        obj->otyp == UNICORN_HORN || obj->oclass == GEM_CLASS) {
  553.         if(obj->otyp < DART || obj->oclass == GEM_CLASS) {
  554.             if (!uwep ||
  555.             objects[obj->otyp].w_propellor !=
  556.             -objects[uwep->otyp].w_propellor) {
  557.             tmp -= 4;
  558.             } else {
  559.             tmp += uwep->spe - uwep->oeroded;
  560.             /*
  561.              * Elves and Samurais are highly trained w/bows,
  562.              * especially their own special types of bow.
  563.              * Polymorphing won't make you a bow expert.
  564.              */
  565.             if ((pl_character[0] == 'E' || pl_character[0] == 'S')
  566.                  && -objects[uwep->otyp].w_propellor == WP_BOW)
  567.                 tmp++;
  568.             if (pl_character[0] == 'E' && uwep->otyp == ELVEN_BOW)
  569.                 tmp++;
  570.             if (pl_character[0] == 'S' && uwep->otyp == YUMI)
  571.                 tmp++;
  572.             }
  573.         } else if(obj->otyp == BOOMERANG) tmp += 4;
  574.         tmp += obj->spe;
  575.         tmp += hitval(obj, mon->data);
  576.         if(tmp >= rnd(20)) {
  577.             if(hmon(mon,obj,1)){
  578.               /* mon still alive */
  579.               cutworm(mon, bhitpos.x, bhitpos.y, obj);
  580.             }
  581.             exercise(A_DEX, TRUE);
  582.             /* projectiles thrown disappear sometimes */
  583.             if((obj->otyp < BOOMERANG || obj->oclass == GEM_CLASS)
  584.                                 && rn2(3)) {
  585.                     if(*u.ushops)
  586.                              check_shop_obj(obj, bhitpos.x, 
  587.                                    bhitpos.y, TRUE);
  588.                 /* check bill; free */
  589.                 obfree(obj, (struct obj *)0);
  590.                 return(1);
  591.             }
  592.         } else miss(xname(obj), mon);
  593.     } else if(obj->otyp == HEAVY_IRON_BALL) {
  594.         if(obj != uball) tmp += 2;
  595.         exercise(A_STR, TRUE);
  596.         if(tmp >= rnd(20)) {
  597.             (void) hmon(mon,obj,1);
  598.             exercise(A_DEX, TRUE);
  599.         } else miss(xname(obj), mon);
  600.     } else if (obj->otyp == BOULDER) {
  601.         tmp += 6;  /* Likely to hit! */
  602.         exercise(A_STR, TRUE);
  603.         if(tmp >= rnd(20)) {
  604.             (void) hmon(mon,obj,1);
  605.             exercise(A_DEX, TRUE);
  606.         } else miss(xname(obj), mon);
  607.     } else if((obj->otyp == CREAM_PIE
  608. #ifdef POLYSELF
  609.             || obj->otyp == BLINDING_VENOM
  610. #endif
  611.                     ) && ACURR(A_DEX) >= rnd(10)) {
  612.         (void) hmon(mon,obj,1); /* can't die from it */
  613. #ifdef POLYSELF
  614.     } else if(obj->otyp == ACID_VENOM && ACURR(A_DEX) >= rnd(10)) {
  615.         (void) hmon(mon,obj,1);
  616. #endif
  617.     } else if(obj->oclass == POTION_CLASS && ACURR(A_DEX) >= rnd(15)) {
  618.         potionhit(mon, obj);
  619.         return(1);
  620.     } else {
  621.         pline("%s misses %s.", The(xname(obj)), mon_nam(mon));
  622.         if(obj->oclass == FOOD_CLASS && is_domestic(mon->data))
  623.             if(tamedog(mon,obj)) return(1);
  624.     }
  625.     return(0);
  626. }
  627.  
  628. static int
  629. gem_accept(mon, obj)
  630. register struct monst *mon;
  631. register struct obj *obj;
  632. {
  633.     char buf[BUFSZ];
  634.     boolean is_buddy = sgn(mon->data->maligntyp) == sgn(u.ualign.type);
  635.     boolean is_gem = objects[obj->otyp].oc_material == GEMSTONE;
  636.     int ret = 0;
  637.     static NEARDATA const char nogood[] = " is not interested in your junk.";
  638.     static NEARDATA const char acceptgift[] = " accepts your gift.";
  639.     static NEARDATA const char maybeluck[] = " hesitatingly";
  640.     static NEARDATA const char noluck[] = " graciously";
  641.     static NEARDATA const char addluck[] = " gratefully";
  642.  
  643.     Strcpy(buf,Monnam(mon));
  644.  
  645.     mon->mpeaceful = 1;
  646.  
  647.     /* object properly identified */
  648.     if(obj->dknown && objects[obj->otyp].oc_name_known) {
  649.         if(is_gem) {
  650.             if(is_buddy) {
  651.                 Strcat(buf,addluck);
  652.                 change_luck(5);
  653.             } else {
  654.                 Strcat(buf,maybeluck);
  655.                 change_luck(rn2(7)-3);
  656.             }
  657.         } else {
  658.             Strcat(buf,nogood);
  659.             goto nopick;
  660.         }
  661.     /* making guesses */
  662.     } else if(obj->onamelth || objects[obj->otyp].oc_uname) {
  663.         if(is_gem) {
  664.             if(is_buddy) {
  665.                 Strcat(buf,addluck);
  666.                 change_luck(2);
  667.             } else {
  668.                 Strcat(buf,maybeluck);
  669.                 change_luck(rn2(3)-1);
  670.             }
  671.         } else {
  672.             Strcat(buf,nogood);
  673.             goto nopick;
  674.         }
  675.     /* value completely unknown to @ */
  676.     } else {
  677.         if(is_gem) {
  678.             if(is_buddy) {
  679.                 Strcat(buf,addluck);
  680.                 change_luck(1);
  681.             } else {
  682.                 Strcat(buf,maybeluck);
  683.                 change_luck(rn2(3)-1);
  684.             }
  685.         } else {
  686.             Strcat(buf,noluck);
  687.         }
  688.     }
  689.      Strcat(buf,acceptgift);
  690.     mpickobj(mon, obj);
  691.     if(*u.ushops) check_shop_obj(obj, mon->mx, mon->my, TRUE);
  692.     ret = 1;
  693.  
  694. nopick:
  695.     if(!Blind) pline(buf);
  696.     rloc(mon);
  697.     return(ret);
  698. }
  699.  
  700. /* returns 0 if object doesn't break    */
  701. /* returns 1 if object broke         */
  702. int
  703. breaks(obj, loose)
  704. register struct obj   *obj;
  705. register boolean loose;        /* if not loose, obj is in fobj chain */
  706. {
  707.     if (obj_resists(obj, 1, 100)) return 0;
  708.  
  709.     switch(obj->otyp) {
  710.         case MIRROR:
  711.             change_luck(-2);    /* and fall through */
  712.         case CRYSTAL_BALL:
  713. #ifdef TOURIST
  714.         case EXPENSIVE_CAMERA:
  715. #endif
  716.             if(!Blind)
  717.                 pline("%s shatters into a thousand pieces!",
  718.                 Doname2(obj));
  719.             else You("hear something shatter!");
  720.             break;
  721.         case EGG:
  722.             pline("Splat!");
  723.             break;
  724.         case CREAM_PIE:
  725.             pline("What a mess!");
  726.             break;
  727.         case ACID_VENOM:
  728.         case BLINDING_VENOM:
  729.             pline("Splash!");
  730.             break;
  731.         default:
  732.             return 0;
  733.     }
  734.  
  735.     /* it is currently assumed that 'loose' is co-extensive
  736.      * with 'thrown'.  if this changes, an explicit 'thrown'
  737.      * arg must be added to breaks() to ensure proper 
  738.      * treatment of shop objs.
  739.      */
  740.     if(loose) {
  741.         newsym(obj->ox,obj->oy);
  742.         if(*u.ushops) 
  743.                 check_shop_obj(obj, obj->ox, obj->oy, TRUE);
  744.         obfree(obj, (struct obj *)0);
  745.     } else {
  746.         /* it is assumed that the obj is a floor-object */ 
  747.         register struct monst *shkp = 0;
  748.         boolean costly, insider;
  749.         long loss = 0L;
  750.  
  751.         costly = (costly_spot(obj->ox, obj->oy) && 
  752.                    (shkp = shop_keeper(*in_rooms(obj->ox,
  753.                   obj->oy, SHOPBASE))) != (struct monst *)0);
  754.         insider = (*u.ushops && inside_shop(u.ux, u.uy) &&
  755.              *in_rooms(obj->ox, obj->oy, SHOPBASE) == *u.ushops);
  756.  
  757.         if(costly)
  758.             loss = stolen_value(obj, u.ux, u.uy, 
  759.                  (shkp && shkp->mpeaceful), FALSE);
  760.         if(loss && !insider)
  761.             make_angry_shk(shkp, obj->ox, obj->oy);
  762.  
  763.         delobj(obj);
  764.     }
  765.     return(1);
  766. }
  767.  
  768. /*
  769.  *  Note that the gold object is *not* attached to the fobj chain.
  770.  */
  771. static int
  772. throw_gold(obj)
  773. struct obj *obj;
  774. {
  775.     int range, odx, ody;
  776.     long zorks = obj->quan;
  777.     register struct monst *mon;
  778.  
  779.     if(u.uswallow) {
  780.         pline(is_animal(u.ustuck->data) ?
  781.             "%s in the %s's entrails." : "%s into %s.",
  782.             "The gold disappears", mon_nam(u.ustuck));
  783.         u.ustuck->mgold += zorks;
  784.         dealloc_obj(obj);
  785.         return(1);
  786.     }
  787.  
  788.     if(u.dz) {
  789.           if(u.dz < 0 && !Is_airlevel(&u.uz) && !Underwater && !Is_waterlevel(&u.uz)) {
  790.     pline("The gold hits the ceiling, then falls back on top of your %s.",
  791.             body_part(HEAD));
  792.             /* some self damage? */
  793.             if(uarmh) pline("Fortunately, you are wearing a helmet!");
  794.         }
  795.         if(flooreffects(obj,u.ux,u.uy,"fall")) return(1);
  796.         if(u.dz > 0) pline("The gold hits the %s.", surface(u.ux,u.uy));
  797.         obj->nobj = fobj;    /* add the gold to the object list */
  798.         fobj = obj;
  799.         place_object(obj,u.ux,u.uy);
  800.         if(*u.ushops) sellobj(obj, u.ux, u.uy);
  801.         stackobj(obj);
  802.         newsym(u.ux,u.uy);
  803.         return 1;
  804.     }
  805.  
  806.     /* consistent with range for normal objects */
  807.     range = (int)((ACURRSTR)/2 - obj->owt/40);
  808.  
  809.     /* see if the gold has a place to move into */
  810.     odx = u.ux + u.dx;
  811.     ody = u.uy + u.dy;
  812.     if(!ZAP_POS(levl[odx][ody].typ) || closed_door(odx, ody)) {
  813.         bhitpos.x = u.ux;
  814.         bhitpos.y = u.uy;
  815.     } else {
  816.         mon = bhit(u.dx, u.dy, range, THROWN_WEAPON,
  817.                    (int (*)()) 0, (int (*)()) 0, obj);
  818.         if(mon) {
  819.             if (ghitm(mon, obj))    /* was it caught? */
  820.             return 1;
  821.         } else {
  822.             if(ship_object(obj, bhitpos.x, bhitpos.y, FALSE)) 
  823.                 return 1;
  824.         }
  825.     }
  826.  
  827.     if(flooreffects(obj,bhitpos.x,bhitpos.y,"fall")) return(1);
  828.     obj->nobj = fobj;    /* add the gold to the object list */
  829.     fobj = obj;
  830.     place_object(obj,bhitpos.x,bhitpos.y);
  831.     if(*u.ushops) sellobj(obj, bhitpos.x, bhitpos.y);
  832.     stackobj(obj);
  833.     newsym(bhitpos.x,bhitpos.y);
  834.     return(1);
  835. }
  836.  
  837. /*dothrow.c*/
  838.